package com.xiguaji.tiktok.task.blogger.event;

import com.google.common.eventbus.AllowConcurrentEvents;
import com.google.common.eventbus.Subscribe;
import com.gugee.tiktok.common.model.dal.blogger.BloggerRepository;
import com.gugee.tiktok.common.model.dto.SlimBloggerDto;
import com.gugee.tiktok.common.model.mysql.Blogger;
import com.gugee.tiktok.common.model.spider.blogger.BloggerResponse;
import com.xiguaji.boot.eventbus.Event;
import com.xiguaji.boot.eventbus.IEventListener;
import com.xiguaji.boot.toolkit.ThreadPoolUtils;
import com.xiguaji.tiktok.task.blogger.spider.BloggerSpiderClient;
import com.xiguaji.tiktok.task.common.config.AppConfig;
import com.xiguaji.tiktok.task.core.ScheduleTemplate;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import javax.annotation.PostConstruct;
import java.util.List;
import java.util.concurrent.*;
import java.util.stream.Collectors;

@Component
@Slf4j
public class SaveBloggerEventListener implements IEventListener<SaveBloggerEventListener.SaveBloggerEvent> {
    ForkJoinPool forkJoinPool = ThreadPoolUtils.forkJoinPool(100, "SaveBlogger-worker");

    @Autowired
    BloggerRepository bloggerRepository;

    @Autowired
    BloggerSpiderClient bloggerSpiderClient;

    @Autowired
    Blogger.BloggerMapper bloggerMapper;

    @Autowired
    ScheduleTemplate scheduleTemplate;
    @Autowired
    AppConfig appConfig;
    @PostConstruct
    public void init() {
        scheduleTemplate.attach("SaveBlogger-worker", forkJoinPool);
    }

    @SneakyThrows
    @Override
    @Subscribe
    @AllowConcurrentEvents
    public void handle(SaveBloggerEvent event) {
        if (!event.needUpdate) {
            //过滤一轮不需要update的Id,减轻bloggerClient压力
            List<Long> uids = bloggerRepository.getNotExistBloggerIds(
                    event.users.stream().map(user -> user.getUid()).collect(Collectors.toList()));

            event.users = event.users.stream()
                    .filter(user -> uids.contains(user.getUid()))
                    .collect(Collectors.toList());
        }

        if (CollectionUtils.isEmpty(event.users)) return;

        forkJoinPool.submit(() ->
                event.users.parallelStream().forEach(user -> {
                    try {
                        run(event, user.getUid(), user.getRegion());
                    } catch (Exception ex) {
                        log.error("SaveBlogger error. uid:" + user.getUid(), ex);
                    }
                })
        ).get();
    }

    public void run(SaveBloggerEvent event, long uid, String region) {
        BloggerResponse bloggerResponse = bloggerSpiderClient.get(uid, region);
        if (bloggerResponse == null || bloggerResponse.getUser() == null) {
            return;
        }

        if(bloggerResponse.getUser().getFollower_count() < appConfig.getCollectFollowerCount()){
            return;
        }


        Blogger blogger = bloggerMapper.mapper(bloggerResponse.getUser());
        if (event.needUpdate) {
            bloggerRepository.insertOrUpdate(blogger, event.getSource());
        } else {
            bloggerRepository.insertWhenNotExists(blogger, event.getSource());
        }
    }

    public static class SaveBloggerEvent extends Event {

        public SaveBloggerEvent(Event event, List<SlimBloggerDto> users, boolean needUpdate) {
            super(event, "SaveBlogger");
            this.users = users;
            this.needUpdate = needUpdate;
        }

        private List<SlimBloggerDto> users;

        private boolean needUpdate;
    }
}
